package com.wuliming.gulimall.product.service.impl;

import cn.hutool.core.util.StrUtil;
import com.wuliming.gulimall.product.dao.CategoryDao;
import com.wuliming.gulimall.product.entity.CategoryEntity;
import com.wuliming.gulimall.product.entity.vo.CateLeve2Vo;
import com.wuliming.gulimall.product.service.CategoryBrandRelationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wuliming.common.utils.PageUtils;
import com.wuliming.common.utils.Query;

import com.wuliming.gulimall.product.service.CategoryService;
import org.springframework.transaction.annotation.Transactional;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    private CategoryBrandRelationService categoryBrandRelationService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<CategoryEntity> listWithTree() {
        List<CategoryEntity> categoryEntities = baseMapper.selectList(null);
        List<CategoryEntity> categoryEntityList = categoryEntities.parallelStream().filter(categoryEntity -> categoryEntity.getParentCid() == 0)
                .map(menus -> {
                    menus.setChildren(getChildren(menus, categoryEntities));
                    return menus;
                })
                .sorted((menus1, menus2) -> {
                    return (menus1.getSort() == null ? 0 : menus1.getSort()) - (menus2.getSort() == null ? 0 : menus2.getSort());
                })
                .collect(Collectors.toList());
        return categoryEntityList;
    }

    @Override
    public void removeMenusByIds(List<Long> list) {
        //TODO 检查分类是否被引用
        baseMapper.deleteBatchIds(list);
    }

    @Override
    public Long[] getCatelogPath(Long catelogId) {
        ArrayList<Long> longs = new ArrayList<>();
        longs = getParentPath(catelogId, longs);
        return longs.toArray(new Long[longs.size()]);
    }

    @Override
    @Transactional
    public void updateByDetail(CategoryEntity category) {
        updateById(category);
        String categoryName = category.getName();
        if (StrUtil.isNotEmpty(categoryName)) {
            categoryBrandRelationService.updateByCategoryName(category.getCatId(), categoryName);
        }
    }

    @Override
    public List<CategoryEntity> getLevel1Category() {
        return list(new QueryWrapper<CategoryEntity>().eq("cat_level", 1));
    }

    @Override
    public Map<String, List<CateLeve2Vo>> getCatalogJson() {
        List<CategoryEntity> list = baseMapper.selectList(null);
        List<CategoryEntity> level1Category = getCategoryEntities(list, 0L);
        Map<String, List<CateLeve2Vo>> level2Category = level1Category.stream().collect(Collectors.toMap(k -> k.getCatId().toString(), l1 -> {
            //封装二级分类
            List<CategoryEntity> categoryEntities = getCategoryEntities(list, l1.getCatId());
            List<CateLeve2Vo> leve2Vos = new ArrayList<>();
            if (categoryEntities != null) {
                categoryEntities.forEach(l2 -> {
                    CateLeve2Vo cateLeve2Vo = new CateLeve2Vo();
                    cateLeve2Vo.setCatalog1Id(l1.getCatId().toString());
                    cateLeve2Vo.setName(l2.getName());
                    cateLeve2Vo.setId(l2.getCatId().toString());
                    //封装三级分类
                    List<CategoryEntity> level3Category = getCategoryEntities(list, l2.getCatId());
                    if (level3Category != null) {
                        List<CateLeve2Vo.CateLeve3Vo> leve3Vos = level3Category.stream().map(l3 -> {
                            CateLeve2Vo.CateLeve3Vo cateLeve3Vo = new CateLeve2Vo.CateLeve3Vo();
                            cateLeve3Vo.setCatalog2Id(l2.getCatId().toString());
                            cateLeve3Vo.setName(l3.getName());
                            cateLeve3Vo.setId(l3.getCatId().toString());
                            return cateLeve3Vo;
                        }).collect(Collectors.toList());
                        cateLeve2Vo.setCatalog3List(leve3Vos);
                    }
                    leve2Vos.add(cateLeve2Vo);
                });
            }
            return leve2Vos;
        }));
        return level2Category;
    }

    private List<CategoryEntity> getCategoryEntities(List<CategoryEntity> categoryEntities, Long parentId) {
        return categoryEntities.stream().filter(w -> w.getParentCid() == parentId)
                .collect(Collectors.toList());
    }

    private ArrayList<Long> getParentPath(Long catelogId, ArrayList<Long> longs) {
        longs.add(catelogId);
        CategoryEntity category = this.getById(catelogId);
        Long parentCid = category.getParentCid();
        if (parentCid != 0) {
            getParentPath(parentCid, longs);
        }
        Collections.reverse(longs);
        return longs;
    }


    private List<CategoryEntity> getChildren(CategoryEntity menus, List<CategoryEntity> all) {
        List<CategoryEntity> entityList = all.parallelStream().filter(categoryEntity -> menus.getCatId() == categoryEntity.getParentCid())
                .map(item -> {
                    item.setChildren(getChildren(item, all));
                    return item;
                }).sorted((menus1, menus2) -> {
                    return (menus1.getSort() == null ? 0 : menus1.getSort()) - (menus2.getSort() == null ? 0 : menus2.getSort());
                })
                .collect(Collectors.toList());
        return entityList;
    }

}